package com.leyou.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.api.R;
import com.leyou.pojo.UserEntity;
import com.leyou.user.constant.AuthServerConstant;
import com.leyou.user.dao.UserDao;
import com.leyou.user.feign.SendCode;
import com.leyou.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;


@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    @Resource
    SendCode sendCode;
   
    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 生成指定位数的随机数字
     * @param len 随机数的位数
     * @return 生成的随机数
     */
    public static String generateCode(int len){
        len = Math.min(len, 8);
        int min = Double.valueOf(Math.pow(10, len - 1)).intValue();
        int num = new Random().nextInt(
                Double.valueOf(Math.pow(10, len + 1)).intValue() - 1) + min;
        return String.valueOf(num).substring(0,len);
    }

    /**
     * 发送手机验证码
     *
     * @param phone
     * @return
     */
    @Override
    public Boolean sendcode(String phone) {
        // 生成6位数验证码
        String code =generateCode(6);
        //  存入redis  验证码的key 前缀加对应的手机号
        String prefixPhone =  AuthServerConstant.SMS_CODE_CACHE_PREFIX+phone;
        // 取出redis中的验证码
        String redisCode = redisTemplate.opsForValue().get(prefixPhone);
        //判断是否为空
        if (!StringUtils.isEmpty(redisCode)){
            long l = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() -l < 60000){
                //60秒内不能再发
                return false;
            }
        }
        //  将验证码存入redis中  格式  验证码_当前系统时间
        redisTemplate.opsForValue().set(prefixPhone,code + "_" + System.currentTimeMillis(),10, TimeUnit.MINUTES);
        //调用第三方微服务中的短信接口
        R r = sendCode.sendSms(phone, code);
        if(r.getCode() != 0){
            log.error("发送短信失败。phone：{}， code：{}", phone, code);
            return false;
        }
        return true;
    }

    /**
     * 账号注册
     *
     * @param user
     * @return
     */
    @Override
    @Transactional
    public Boolean register(UserEntity user) {
        //  存入redis  验证码的key 前缀加对应的手机号
        String prefixPhone =  AuthServerConstant.SMS_CODE_CACHE_PREFIX+user.getPhone();
        // 取出redis中的验证码
        String redisCode = redisTemplate.opsForValue().get(prefixPhone);
        //判断验证码是否输入正确
        if(!StringUtils.isEmpty(redisCode)){
            String[] split = redisCode.split("_");
            if (!split[0].equals(user.getCode()))
            return false;
        }else {
            return false;
        }
        // 密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setCreated(new Date());
        this.save(user);
        // 删除验证码
        redisTemplate.delete(prefixPhone);
        return true;
    }

    /**
     * 校验数据是否可用
     *
     * @param data
     * @param type 1为用户名 2为手机号
     * @return
     */
    @Override
    public Boolean checkData(String data, Integer type) {
        String param = "";
        if(type ==1){
            param = "username";
        }else if (type == 2){
            param = "phone";
        }
        UserEntity username = this.getOne(new QueryWrapper<UserEntity>().eq(param, data));
        return username == null ? true : false;
    }

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public UserEntity queryUser(String username, String password) {

        UserEntity user = this.getOne(new QueryWrapper<UserEntity>().eq("username", username));
        if(user == null){
            user = this.getOne(new QueryWrapper<UserEntity>().eq("phone", username));
        }
        if(user != null){
            // 加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            //解密
            boolean matches = passwordEncoder.matches(password, user.getPassword());
            if(matches){
                return user;
            }
        }
        return null;
    }
}